package org.hiro.psi;

import com.intellij.psi.*;
import com.intellij.psi.codeStyle.CodeStyleManager;

public class NewEmptyObjectMethodBuilder<T extends NewEmptyObjectMethodBuilder> extends PsiMethodBuilder<NewEmptyObjectMethodBuilder> {
    private PsiClass classToBuild;

    public NewEmptyObjectMethodBuilder(PsiElementFactory elementFactory, CodeStyleManager codeStyleManager) {
        super(elementFactory, codeStyleManager);
    }

    @Override
    public PsiMethod build() {
        withMethodText(createMethodText());
        return super.build();
    }

    private String createMethodText() {
        String returnType = classToBuild.getContainingFile().getName().split("\\.")[0];
        String parameterList = createParameterList(getFirstNonPrivateConstructor(classToBuild.getConstructors()));
        return "protected " + returnType + " newEmptyObject() {" +
                "return " + " new " + returnType + "(" + parameterList + ");}";
    }

    private PsiMethod getFirstNonPrivateConstructor(PsiMethod[] psiConstructors) {
        if (psiConstructors.length > 0) {
            for (PsiMethod psiConstructor : psiConstructors) {
                if (!psiConstructor.getModifierList().hasModifierProperty("private")) {
                    return psiConstructor;
                }
            }
        }
        return null;
    }

    private String createParameterList(PsiMethod constructor) {
        String parameterList = "";

        if (constructor != null) {
            PsiParameter[] parameters = constructor.getParameterList().getParameters();
            for (PsiParameter psiParameter : parameters) {
                PsiType type = psiParameter.getType();

                if (type.equals(PsiType.INT)) {
                    parameterList += "0, ";
                } else if (type.equals(PsiType.LONG)) {
                    parameterList += "0L, ";
                } else if (type.equals(PsiType.CHAR)) {
                    parameterList += "(char)0, ";
                } else if (type.equals(PsiType.BYTE)) {
                    parameterList += "(byte)0, ";
                } else if (type.equals(PsiType.SHORT)) {
                    parameterList += "(short)0, ";
                } else if (type.equals(PsiType.FLOAT)) {
                    parameterList += "0.0F, ";
                } else if (type.equals(PsiType.DOUBLE)) {
                    parameterList += "0.0D, ";
                } else if (type.equals(PsiType.BOOLEAN)) {
                    parameterList += "true, ";
                } else {
                    parameterList += "null, ";
                }
            }

            if (parameters.length > 0) {
                parameterList = parameterList.substring(0, parameterList.length() - 2);
            }
        }
        return parameterList;
    }

    public T withClassToBuild(PsiClass classToBuild) {
        this.classToBuild = classToBuild;
        return (T) this;
    }
}